be returned by XENMEM_memory_map. Hook this into the domain builder.
Based on a patch by Glauber de Oliveira Costa <gcosta@redhat.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
return do_domctl(xc_handle, &domctl);
}
+#if defined(__i386__) || defined(__x86_64__)
+#include <xen/hvm/e820.h>
+int xc_domain_set_memmap_limit(int xc_handle,
+ uint32_t domid,
+ unsigned long map_limitkb)
+{
+ int rc;
+
+ struct xen_foreign_memory_map fmap = {
+ .domid = domid,
+ .map = { .nr_entries = 1 }
+ };
+
+ struct e820entry e820 = {
+ .addr = 0,
+ .size = (uint64_t)map_limitkb << 10,
+ .type = E820_RAM
+ };
+
+ set_xen_guest_handle(fmap.map.buffer, &e820);
+
+ if ( lock_pages(&fmap, sizeof(fmap)) || lock_pages(&e820, sizeof(e820)) )
+ {
+ PERROR("Could not lock memory for Xen hypercall");
+ rc = -1;
+ goto out;
+ }
+
+ rc = xc_memory_op(xc_handle, XENMEM_set_memory_map, &fmap);
+
+ out:
+ unlock_pages(&fmap, sizeof(fmap));
+ unlock_pages(&e820, sizeof(e820));
+ return rc;
+}
+#else
+int xc_domain_set_memmap_limit(int xc_handle,
+ uint32_t domid,
+ unsigned long map_limitkb)
+{
+ PERROR("Function not implemented");
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
int xc_domain_set_time_offset(int xc_handle,
uint32_t domid,
int32_t time_offset_seconds)
uint32_t domid,
unsigned int max_memkb);
+int xc_domain_set_memmap_limit(int xc_handle,
+ uint32_t domid,
+ unsigned long map_limitkb);
+
int xc_domain_set_time_offset(int xc_handle,
uint32_t domid,
int32_t time_offset_seconds);
return zero;
}
+static PyObject *pyxc_domain_set_memmap_limit(XcObject *self, PyObject *args)
+{
+ uint32_t dom;
+ unsigned int maplimit_kb;
+
+ if ( !PyArg_ParseTuple(args, "ii", &dom, &maplimit_kb) )
+ return NULL;
+
+ if ( xc_domain_set_memmap_limit(self->xc_handle, dom, maplimit_kb) != 0 )
+ return pyxc_error_to_exception();
+
+ Py_INCREF(zero);
+ return zero;
+}
+
static PyObject *pyxc_domain_memory_increase_reservation(XcObject *self,
PyObject *args,
PyObject *kwds)
" maxmem_kb [int]: .\n"
"Returns: [int] 0 on success; -1 on error.\n" },
+ { "domain_set_memmap_limit",
+ (PyCFunction)pyxc_domain_set_memmap_limit,
+ METH_VARARGS, "\n"
+ "Set a domain's physical memory mappping limit\n"
+ " dom [int]: Identifier of domain.\n"
+ " map_limitkb [int]: .\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
{ "domain_memory_increase_reservation",
(PyCFunction)pyxc_domain_memory_increase_reservation,
METH_VARARGS | METH_KEYWORDS, "\n"
return max(4 * (256 * self.vm.getVCpuCount() + 2 * (maxmem_kb / 1024)),
shadow_mem_kb)
+class X86_Linux_ImageHandler(LinuxImageHandler):
+
+ def buildDomain(self):
+ # set physical mapping limit
+ # add an 8MB slack to balance backend allocations.
+ mem_kb = self.getRequiredInitialReservation() + (8 * 1024)
+ xc.domain_set_memmap_limit(self.vm.getDomid(), mem_kb)
+ return LinuxImageHandler.buildDomain(self)
_handlers = {
"powerpc": {
"hvm": IA64_HVM_ImageHandler,
},
"x86": {
- "linux": LinuxImageHandler,
+ "linux": X86_Linux_ImageHandler,
"hvm": X86_HVM_ImageHandler,
},
}
break;
}
+ case XENMEM_set_memory_map:
+ {
+ struct xen_foreign_memory_map fmap;
+ struct domain *d;
+ int rc;
+
+ if ( copy_from_guest(&fmap, arg, 1) )
+ return -EFAULT;
+
+ if ( fmap.map.nr_entries > ARRAY_SIZE(d->arch.e820) )
+ return -EINVAL;
+
+ if ( fmap.domid == DOMID_SELF )
+ {
+ d = current->domain;
+ get_knownalive_domain(d);
+ }
+ else if ( !IS_PRIV(current->domain) )
+ return -EPERM;
+ else if ( (d = find_domain_by_id(fmap.domid)) == NULL )
+ return -ESRCH;
+
+ rc = copy_from_guest(&d->arch.e820[0], fmap.map.buffer,
+ fmap.map.nr_entries) ? -EFAULT : 0;
+ d->arch.nr_e820 = fmap.map.nr_entries;
+
+ put_domain(d);
+ return rc;
+ }
+
case XENMEM_memory_map:
{
- return -ENOSYS;
+ struct xen_memory_map map;
+ struct domain *d = current->domain;
+
+ /* Backwards compatibility. */
+ if ( d->arch.nr_e820 == 0 )
+ return -ENOSYS;
+
+ if ( copy_from_guest(&map, arg, 1) )
+ return -EFAULT;
+
+ map.nr_entries = min(map.nr_entries, d->arch.nr_e820);
+ if ( copy_to_guest(map.buffer, &d->arch.e820[0], map.nr_entries) ||
+ copy_to_guest(arg, &map, 1) )
+ return -EFAULT;
+
+ return 0;
}
case XENMEM_machine_memory_map:
#include <xen/mm.h>
#include <asm/hvm/vcpu.h>
#include <asm/hvm/domain.h>
+#include <asm/e820.h>
struct trap_bounce {
unsigned long error_code;
/* I/O-port admin-specified access capabilities. */
struct rangeset *ioport_caps;
- /* HVM stuff */
- struct hvm_domain hvm_domain;
-
- /* Shadow-translated guest: Pseudophys base address of reserved area. */
- unsigned long first_reserved_pfn;
+ struct hvm_domain hvm_domain;
struct shadow_domain shadow;
/* Highest guest frame that's ever been mapped in the p2m */
unsigned long max_mapped_pfn;
+ /* Pseudophysical e820 map (XENMEM_memory_map). */
+ struct e820entry e820[3];
+ unsigned int nr_e820;
} __cacheline_aligned;
#ifdef CONFIG_X86_PAE
/*
* Returns the pseudo-physical memory map as it was when the domain
- * was started.
+ * was started (specified by XENMEM_set_memory_map).
+ * arg == addr of xen_memory_map_t.
*/
#define XENMEM_memory_map 9
struct xen_memory_map {
/*
* Returns the real physical memory map. Passes the same structure as
* XENMEM_memory_map.
+ * arg == addr of xen_memory_map_t.
*/
#define XENMEM_machine_memory_map 10
+/*
+ * Set the pseudo-physical memory map of a domain, as returned by
+ * XENMEM_memory_map.
+ * arg == addr of xen_foreign_memory_map_t.
+ */
+#define XENMEM_set_memory_map 13
+struct xen_foreign_memory_map {
+ domid_t domid;
+ struct xen_memory_map map;
+};
+typedef struct xen_foreign_memory_map xen_foreign_memory_map_t;
+DEFINE_XEN_GUEST_HANDLE(xen_foreign_memory_map_t);
+
#endif /* __XEN_PUBLIC_MEMORY_H__ */
/*